// Dwarf.Unmanaged.Serial.cpp : Defines the entry point for the console application.
//

#include "Dwarf.Unmanaged.Hybrid.h"

using namespace std;

// The settings for this dwarf.
static Settings* settings;

// Get settings from the command line.
static int getSettings(int argc, char** argv, Solver *slasolver) 
{
    int error = 0;
    if (slasolver->isRootThread) 
    {
        settings = new Settings();
        if (settings->init(argc,argv,slasolver))            //Parse all arguments for dwarf.
        {            
            delete settings;
            error = 1;
        }
    }    

    //Distribute error if that occurred while parsing.
    MPI_Bcast(&error, 1, MPI_INT, NUMBER_ROOT_PROCESS, MPI_COMM_WORLD);       

    if (error) return -1;

    //Distribute number of rows.
    MPI_Bcast(&slasolver->rowNum, 1, MPI_INT, NUMBER_ROOT_PROCESS, MPI_COMM_WORLD);

    //Init arrays.
    if (!slasolver->isRootThread) 
    {
        slasolver->val = new double[slasolver->rowNum];
        slasolver->col_ind = new int[slasolver->rowNum];
        slasolver->vector = new double[slasolver->rowNum];
    }

    //Distribute vector.
    MPI_Bcast(slasolver->vector, slasolver->rowNum, MPI_DOUBLE, NUMBER_ROOT_PROCESS, MPI_COMM_WORLD);

    return 0;
}

// Point of the program start.
void main(int argc, char** argv)
{   

    Solver* slasolver = new Solver(); 

    if (slasolver->commSize == 1) 
    {
        delete slasolver;
        printf("Only one mpi process.");
        exit(-1);
    }

    if (getSettings(argc, argv, slasolver))             // Get settings from the command line.
    {
        delete slasolver;
        exit(-1);
    }

    MPI_Barrier(MPI_COMM_WORLD);

    if (slasolver->isRootThread) 
    {
        settings->start();                              // Start new time count.
    }

    //This line of code is used for decrease of input file size.
	//Such modification would reduce the input file size, 
	//but the algorithm is still belongs dwarf.
	//Also this line does not affect the result.
	for (int k = 0; k < 200; k ++)
	{ slasolver->solve(); }                                // Solve the current problem.

    MPI_Barrier(MPI_COMM_WORLD);

    if (slasolver->isRootThread) 
    {
        settings->finish(slasolver);                    // Stop the time count and write results.
        delete settings;
    }

    delete slasolver;
}
